/**
 * 水印配置接口 可以在这里调试
 */
export interface WatermarkOptions {
  /** 文字颜色 */
  textColor?: string
  /** 背景颜色，支持rgba */
  backgroundColor?: string
  /** 字体大小 */
  fontSize?: number
  /** 水印位置 */
  position?: 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'full'
  /** 水印旋转角度（仅在 position 为 'full' 时生效） */
  rotate?: number
  /** 水印之间的间距（仅在 position 为 'full' 时生效） */
  gap?: number
}

/**
 * 图片处理工具类
 */
export class ImageUtils {
  /**
   * 给图片添加水印
   * @param tempFilePath 图片临时文件路径 上传的时候可以获取到
   * @param address 地址
   * @param options 水印配置
   * @returns Promise<string> 返回处理后的临时文件路径
   */
  static async addWatermark(
    tempFilePath: string,
    address: string,
    options: WatermarkOptions = {},
  ): Promise<string> {
    if (!tempFilePath) {
      throw new Error('tempFilePath is required')
    }

    // 默认配置
    const defaultOptions: Required<WatermarkOptions> = {
      textColor: '#FFFFFF',
      backgroundColor: 'rgba(0, 0, 0, 0.2)',
      fontSize: 14,
      position: 'full',
      rotate: -30,
      gap: 100,
    }

    // 合并配置
    const config = { ...defaultOptions, ...options }

    return new Promise((resolve, reject) => {
      // 获取图片信息 拿到上传图片的地址
      uni.getImageInfo({
        src: tempFilePath,
        success: async (imageInfo) => {
          try {
            // 创建canvas上下文
            const canvasId = 'watermarkCanvas'
            const query = uni.createSelectorQuery()
            const canvas = await new Promise((resolve, reject) => {
              query
                .select(`#${canvasId}`)
                .fields({ node: true, size: true })
                .exec((res) => {
                  if (res[0]) {
                    resolve(res[0].node)
                  } else {
                    reject(new Error('Canvas not found'))
                  }
                })
            })

            const ctx = canvas.getContext('2d')

            // 设置canvas尺寸
            canvas.width = imageInfo.width
            canvas.height = imageInfo.height

            // 创建图片对象
            const image = canvas.createImage()
            await new Promise((resolve, reject) => {
              image.onload = resolve
              image.onerror = reject
              image.src = tempFilePath
            })

            // 绘制原图
            ctx.drawImage(image, 0, 0, imageInfo.width, imageInfo.height)

            // 获取当前时间
            const now = new Date()
            const timeStr = getBeijingTimeISOString()

            const watermarkText = `${timeStr}\n${address}`

            if (config.position === 'full') {
              // 设置水印文字样式
              const fontSize = Math.max(config.fontSize, Math.floor(imageInfo.width * 0.02))
              ctx.font = `${fontSize}px sans-serif`
              ctx.fillStyle = config.textColor
              ctx.textBaseline = 'middle'
              ctx.textAlign = 'center'

              // 计算水印文本的大小
              const textWidth = ctx.measureText(address).width
              const lineHeight = fontSize * 1.5
              const textHeight = lineHeight * 2

              // 保存当前状态
              ctx.save()

              // 设置全局透明度
              ctx.globalAlpha = 0.2

              // 在整个画布上重复绘制水印
              const stepX = textWidth + config.gap
              const stepY = textHeight + config.gap
              const startX = -imageInfo.width
              const endX = imageInfo.width * 2
              const startY = -imageInfo.height
              const endY = imageInfo.height * 2

              for (let x = startX; x < endX; x += stepX) {
                for (let y = startY; y < endY; y += stepY) {
                  ctx.save()
                  ctx.translate(x, y)
                  ctx.rotate((config.rotate * Math.PI) / 180)

                  // 绘制时间
                  ctx.fillText(timeStr, 0, 0)
                  // 绘制地址
                  ctx.fillText(address, 0, lineHeight)

                  ctx.restore()
                }
              }

              // 恢复之前的状态
              ctx.restore()
            } else {
              // 原有的单个水印逻辑
              const fontSize = Math.max(config.fontSize, Math.floor(imageInfo.width * 0.02))
              ctx.font = `${fontSize}px sans-serif`
              ctx.fillStyle = config.textColor
              ctx.textBaseline = 'top'

              const padding = Math.max(10, Math.floor(imageInfo.width * 0.01))
              const lineHeight = fontSize * 1.5
              const timeWidth = ctx.measureText(timeStr).width
              const addressWidth = ctx.measureText(address).width
              const boxWidth = Math.max(timeWidth, addressWidth) + padding * 2
              const boxHeight = lineHeight * 2 + padding * 2

              let x = padding
              let y = padding

              switch (config.position) {
                case 'topRight':
                  x = imageInfo.width - boxWidth - padding
                  break
                case 'bottomLeft':
                  y = imageInfo.height - boxHeight
                  break
                case 'bottomRight':
                  x = imageInfo.width - boxWidth - padding
                  y = imageInfo.height - boxHeight
                  break
              }

              // 绘制水印背景
              ctx.fillStyle = config.backgroundColor
              ctx.fillRect(x, y, boxWidth, boxHeight)

              // 绘制水印文字
              ctx.fillStyle = config.textColor
              ctx.fillText(timeStr, x + padding, y + padding)
              ctx.fillText(address, x + padding, y + padding + lineHeight)
            }

            // 导出图片
            uni.canvasToTempFilePath({
              canvas,
              success: (res) => resolve(res.tempFilePath),
              fail: reject,
            })
          } catch (error) {
            reject(error)
          }
        },
        fail: (error) => reject(error),
      })
    })
  }

  /**
   * 压缩图片 可以处理图片大小
   * @param tempFilePath 图片临时文件路径 一半在组件上传的时候 可以获取临时路径
   * @param quality 压缩质量(0-100)
   * @returns Promise<string> 返回压缩后的临时文件路径
   */
  static async compressImage(tempFilePath: string, quality = 80): Promise<string> {
    return new Promise((resolve, reject) => {
      uni.compressImage({
        src: tempFilePath,
        quality,
        success: (res) => {
          resolve(res.tempFilePath)
        },
        fail: (err) => {
          reject(new Error('压缩图片失败：' + err.errMsg))
        },
      })
    })
  }
}
function getBeijingTimeISOString() {
  throw new Error("Function not implemented.")
}

